/**
 * image loader
 * Copyright (c) 2009 cmiscm.com
 * date of final modification : 2009. 07. 15 
*/
package com.cmiscm.net
{
	import com.cmiscm.net.events.NetEvent;
	
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	
	[Event (name="complete", type="com.cmiscm.net.events.NetEvent")]
	[Event (name="progress", type="com.cmiscm.net.events.NetEvent")]
	[Event (name="error", type="com.cmiscm.net.events.NetEvent")]
	[Event (name="inits", type="com.cmiscm.net.events.NetEvent")]
	[Event (name="server_error", type="com.cmiscm.net.events.NetEvent")]
	
	/**
	 * Image Loader.
     * 
     * @example
     * <listing>
     * package {
     *    import com.cmiscm.net.ImageLoader;
     *    import com.cmiscm.net.events.NetEvent;
     *    
     *    public class TestLoader
     *    {
     *        private var _loader:ImageLoader;
     *        
     *        public function TestLoader()
     *        {
     *            _loader = new XmlLoader();
     *            _loader.addEventListener(NetEvent.COMPLETE, onComplete);            
     *            _loader.addEventListener(NetEvent.PROGRESS, onProgress);
     *            _loader.addEventListener(NetEvent.INITS, onInit);
     *            _loader.addEventListener(NetEvent.ERROR, onError);
     *            _loader.addEventListener(NetEvent.SERVER_ERROR, onServerError);
     *            _loader.load("test.jpg");
     *        }
     *        
     *        private function onComplete(evt:NetEvent):void
     *        {
     *            trace(evt.bitmap);
     *            
     *            _loader.removeEventListener(NetEvent.COMPLETE, onComplete);            
     *            _loader.removeEventListener(NetEvent.PROGRESS, onProgress);
     *            _loader.removeEventListener(NetEvent.INITS, onInit);
     *            _loader.removeEventListener(NetEvent.ERROR, onError);
     *            _loader.removeEventListener(NetEvent.SERVER_ERROR, onServerError);
     *            _loader.garbage();
     *            _loader = null;
     *        }
     *        
     *        private function onProgress(evt:NetEvent):void
     *        {
     *            trace(evt.percent);
     *        }
     *        
     *        private function onInit(evt:NetEvent):void
     *        {
     *            trace("init load");
     *        }
     *        
     *        private function onError(evt:NetEvent):void
     *        {
     *            trace(evt.message);
     *        }
     *        
     *        private function onServerError(evt:NetEvent):void
     *        {
     *            trace(evt.message);
     *        }
     *    }
     * }
     * </listing>
     * 
     * @see com.cmiscm.net.events.NetEvent NetEvent
	 */
	public class ImageLoader extends EventDispatcher
	{
		private var _loader:Loader;
		private var _urlRequest:URLRequest;
		private var _isLoad:Boolean = false;
		private var _total:Number = 0;
				
		public function ImageLoader()
		{
			super();			
		}
		
		/**
		 * Load Image
		 * @param $url Image URL
		 * @param $context LoaderContext
		 * @param $is_cache true in case cache load
		 * 
		 */		
		public function load($url:String, $context:LoaderContext=null, $is_cache:Boolean=false):void
		{
			_loader = new Loader();
			_loader.contentLoaderInfo.addEventListener(Event.INIT, onInit);			
			_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
			_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
			_loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			
			var my_url:String;
			if ($is_cache) {
				if ($url.indexOf("?") == -1) my_url = $url + "?uqcm="+(new Date()).getTime();
				else my_url = $url + "&uqcm="+(new Date()).getTime();
			} else my_url = $url;
			_urlRequest = new URLRequest($url);
			
            try {	
            	_isLoad = true;			
				_loader.load(_urlRequest, $context);
            } catch(e:Error) {
            	_isLoad = false;
				this.dispatchEvent(new NetEvent(NetEvent.ERROR, NetEvent.LOAD_ERROR));
            }
		}
		
		
		/**
		 * Garbage ImageLoader 
		 * 
		 */	
		public function garbage(): void
		{
			removeEvent();
			if (_loader != null) {
				if (_isLoad) {
					try {	
		            	_loader.close();
		            } catch(e:Error) {
		            	
		            }
				}
				_loader = null;
				_urlRequest = null;
			}
			_isLoad = false;
		}
		private function removeEvent():void
		{
			if (_loader != null && _loader.contentLoaderInfo.hasEventListener(Event.COMPLETE)) {
				_loader.contentLoaderInfo.removeEventListener(Event.INIT, onInit);				
				_loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
				_loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onError);
				_loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
				_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
			}
		}
		
		/**
		 * event 
		 */
		private function onInit(evt:Event): void
		{
			this.dispatchEvent(new NetEvent(NetEvent.INITS, null, 0, _loader));
		}		
		private function onComplete(evt:Event): void
		{	
			if (_total == 0) this.dispatchEvent(new NetEvent(NetEvent.SERVER_ERROR, NetEvent.TOTAL_ZERO));
			_isLoad = false;	
			try {		
				var bitmap:Bitmap = _loader.content as Bitmap;		
				this.dispatchEvent(new NetEvent(NetEvent.COMPLETE, null, 1, null, bitmap));
			} catch(e:Error) {
				this.dispatchEvent(new NetEvent(NetEvent.ERROR, NetEvent.COMPLETE_ERROR));
			}
		}
		private function onProgress(evt:ProgressEvent):void
		{
			var loaded:Number = evt.bytesLoaded;
			_total = evt.bytesTotal;
			var percent:Number = loaded / _total;
			this.dispatchEvent(new NetEvent(NetEvent.PROGRESS, null, percent));
		}
		private function onError(evt:IOErrorEvent):void
		{
			_isLoad = false;
			this.dispatchEvent(new NetEvent(NetEvent.ERROR, NetEvent.NO_FILE));
		}
		private function onSecurityError(evt:SecurityErrorEvent):void
		{
			_isLoad = false;
			this.dispatchEvent(new NetEvent(NetEvent.ERROR, NetEvent.SECURITY_ERROR));
		}
	}
}